package com.pactera.madp.cp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pactera.madp.admin.api.entity.SysDept;
import com.pactera.madp.admin.api.entity.SysUser;
import com.pactera.madp.admin.api.feign.RemoteUserService;
import com.pactera.madp.common.core.constant.SecurityConstants;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.common.data.tenant.TenantContextHolder;
import com.pactera.madp.common.security.service.MadpUser;
import com.pactera.madp.common.security.util.SecurityUtils;
import com.pactera.madp.common.sequence.sequence.Sequence;
import com.pactera.madp.cp.api.bo.ToDoListBO;
import com.pactera.madp.cp.api.dto.taskpub.TaskPageDTO;
import com.pactera.madp.cp.api.dto.taskpub.TaskPubDto;
import com.pactera.madp.cp.api.dto.taskpub.TaskPubUpdateDto;
import com.pactera.madp.cp.api.entity.*;
import com.pactera.madp.cp.api.entity.taskpub.TaskPubEntity;
import com.pactera.madp.admin.api.feign.RemoteDeptAdminService;
import com.pactera.madp.cp.api.vo.moments.ToDoListVO;
import com.pactera.madp.cp.api.vo.task.TaskDetailsByEmployeeVO;
import com.pactera.madp.cp.api.vo.task.TaskDetailsByIdVO;
import com.pactera.madp.cp.api.vo.task.TaskPageVO;
import com.pactera.madp.cp.common.constant.BehaviorTrackFormatConst;
import com.pactera.madp.cp.common.util.WxApiUtils;
import com.pactera.madp.cp.handler.CorpContextHolder;
import com.pactera.madp.cp.mapper.TaskPubCustMapper;
import com.pactera.madp.cp.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
public class TaskPubCustServiceImpl extends ServiceImpl<TaskPubCustMapper, TaskPubEntity> implements TaskPubCustService {

    /**
     * 时间格式化常量
     */
    final String dateFormat = "yyyy-MM-dd HH:mm:ss";
    /**
     * 员工信息
     */
    @Resource
    private IWorkEmployeeService workEmployeeService;
    /**
     * 任务-员工信息
     */
    @Resource
    private CpTaskPubEmpService cpTaskPubEmpService;
    /**
     * 员工-客户信息
     */
    @Resource
    private IWorkContactEmployeeService workContactEmployeeService;
    /**
     * 企业信息
     */
    @Resource
    private ICorpService corpService;
    /**
     * 远程调用员工信息
     */
    @Resource
    private RemoteUserService remoteUserService;
    /**
     * 远程调用部门信息
     */
    @Resource
    private RemoteDeptAdminService remoteDeptService;
    @Autowired
    private CpApprovalService cpApprovalService;
    @Autowired
    private Sequence sequence;

    /**
     * 新增任务
     *
     * @param dto
     * @return
     */
    @Override
    public boolean createTask(TaskPubDto dto) {

        MadpUser createUser = SecurityUtils.getUser();

        TaskPubEntity entity = new TaskPubEntity();
        BeanUtil.copyProperties(dto, entity, "joinUser", "deptIds");
        entity.setCreateUser(createUser.getId());
        entity.setCreateUserName(createUser.getUsername());
        entity.setCorpId(CorpContextHolder.getCorpId());
        entity.setTenantId(TenantContextHolder.getTenantId());
        entity.setBeginTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getBeginTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss")));
        entity.setEndTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss")));
        entity.setDeptIds(JSONUtil.toJsonStr(dto.getDeptIds()));

        List<SysUser> userList = new ArrayList<>();
        if (!dto.getDeptIds().isEmpty()) {
            userList = remoteUserService.userByDeptIds(dto.getDeptIds(), SecurityConstants.FROM_IN);
        }

        Set<Integer> userIds = new LinkedHashSet<>();
        Set<String> userJobNos = new LinkedHashSet<>();

        userList.forEach(u -> {
            userIds.add(u.getUserId());
            userJobNos.add(u.getUsername());
        });
        if (dto.getJoinUser() != null && !dto.getJoinUser().isEmpty()) {
            userIds.addAll(dto.getJoinUser());
        }
        if (dto.getJoinJobNo() != null && !dto.getJoinJobNo().isEmpty()) {
            userJobNos.addAll(dto.getJoinJobNo());
        }

        // 排除admin
        userIds.remove(1);
        userJobNos.remove("admin");

        entity.setJoinUser(JSONUtil.toJsonStr(userIds));
        entity.setJoinJobNo(JSONUtil.toJsonStr(userJobNos));

        return save(entity);
    }

    /**
     * 任务分页列表
     *
     * @param dto
     * @param page
     * @return
     */
    @Override
    public Page<TaskPageVO> getPageByOut(TaskPageDTO dto, Page page) {
        List<Integer> statusList = new ArrayList<>();
        if (dto.getState() != null && dto.getState() == 1) {
            // 已发布
            statusList.add(1);
            // 进行中
            statusList.add(2);
            // 已过期
            statusList.add(3);
        } else {
            // 待发布
            statusList.add(0);
            // 待审批
            statusList.add(5);
            // 已驳回
            statusList.add(6);
        }
        LambdaQueryWrapper<TaskPubEntity> wrapper = Wrappers.<TaskPubEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(dto.getCreateUserName()), TaskPubEntity::getCreateUserName, dto.getCreateUserName())
                .between(StrUtil.isNotBlank(dto.getStartTime()) && StrUtil.isNotBlank(dto.getEndTime()), TaskPubEntity::getEndTime, dto.getStartTime() + " 00:00:00", dto.getEndTime() + " 23:59:59")
                .or().like(StrUtil.isNotBlank(dto.getCreateUserName()), TaskPubEntity::getCreateUserName, dto.getCreateUserName())
                .between(StrUtil.isNotBlank(dto.getStartTime()) && StrUtil.isNotBlank(dto.getEndTime()), TaskPubEntity::getBeginTime, dto.getStartTime() + " 00:00:00", dto.getEndTime() + " 23:59:59")
                .in(TaskPubEntity::getStatus, statusList)
                .orderByDesc(TaskPubEntity::getCreateTime);
        page = (Page) this.page(page, wrapper);
        List<TaskPubEntity> list = page.getRecords();
        List<TaskPageVO> vos = new LinkedList<>();
        list.forEach(l -> {
            TaskPageVO vo = new TaskPageVO();
            BeanUtil.copyProperties(l, vo);

            List<String> userNames = new LinkedList<>();
            List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(l.getJoinUser()), Integer.class);

            if (!joinUsers.isEmpty()) {
                List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());

                List<String> strings = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                                .in(WorkEmployeeEntity::getWxUserId, collect))
                        .stream().map(WorkEmployeeEntity::getName).collect(Collectors.toList());
                userNames.addAll(strings);
            }
            List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(l.getDeptIds()), Integer.class);

            if (!deptIds.isEmpty()) {
                List<String> collect = remoteDeptService.getDeptListById(deptIds).stream().map(SysDept::getName).collect(Collectors.toList());
                userNames.addAll(collect);
            }
            vo.setJoinUserName(userNames);

            vo.setBeginTime(l.getBeginTime().format(DateTimeFormatter.ISO_DATE));
            vo.setEndTime(l.getEndTime().format(DateTimeFormatter.ISO_DATE));
            vo.setTitle(l.getTitle());

            if (ObjectUtil.isNotNull(l.getPercentage()) && l.getPercentage().equals(100)) {
                vo.setStatus(4);
            }

            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }

    /**
     * 审批分页列表
     *
     * @param dto
     * @param page
     * @return
     */
    @Override
    public Page<TaskPageVO> getApprovalPageByOut(TaskPageDTO dto, Page page) {
        List<Integer> statusList = new ArrayList<>();
        if (dto.getState() != null && dto.getState() == 1) {
            // 已发布
            statusList.add(1);
            // 进行中
            statusList.add(2);
            // 已过期
            statusList.add(3);
        } else {
            // 待审批
            statusList.add(5);
            // 已驳回
            statusList.add(6);
        }
        LambdaQueryWrapper<TaskPubEntity> wrapper = Wrappers.<TaskPubEntity>lambdaQuery()
                .like(StrUtil.isNotBlank(dto.getCreateUserName()), TaskPubEntity::getCreateUserName, dto.getCreateUserName())
                .between(StrUtil.isNotBlank(dto.getStartTime()) && StrUtil.isNotBlank(dto.getEndTime()), TaskPubEntity::getEndTime, dto.getStartTime() + " 00:00:00", dto.getEndTime() + " 23:59:59")
                .or().like(StrUtil.isNotBlank(dto.getCreateUserName()), TaskPubEntity::getCreateUserName, dto.getCreateUserName())
                .between(StrUtil.isNotBlank(dto.getStartTime()) && StrUtil.isNotBlank(dto.getEndTime()), TaskPubEntity::getBeginTime, dto.getStartTime() + " 00:00:00", dto.getEndTime() + " 23:59:59")
                .in(TaskPubEntity::getStatus, statusList)
                .orderByDesc(TaskPubEntity::getCreateTime);
        page = (Page) this.page(page, wrapper);
        List<TaskPubEntity> list = page.getRecords();
        List<TaskPageVO> vos = new LinkedList<>();
        list.forEach(l -> {
            TaskPageVO vo = new TaskPageVO();
            BeanUtil.copyProperties(l, vo);

            List<String> userNames = new LinkedList<>();
            List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(l.getJoinUser()), Integer.class);

            if (!joinUsers.isEmpty()) {
                List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());

                List<String> strings = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                        .in(WorkEmployeeEntity::getWxUserId, collect))
                        .stream().map(WorkEmployeeEntity::getName).collect(Collectors.toList());
                userNames.addAll(strings);
            }
            List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(l.getDeptIds()), Integer.class);

            if (!deptIds.isEmpty()) {
                List<String> collect = remoteDeptService.getDeptListById(deptIds).stream().map(SysDept::getName).collect(Collectors.toList());
                userNames.addAll(collect);
            }
            vo.setJoinUserName(userNames);

            vo.setBeginTime(l.getBeginTime().format(DateTimeFormatter.ISO_DATE));
            vo.setEndTime(l.getEndTime().format(DateTimeFormatter.ISO_DATE));
            vo.setTitle(l.getTitle());

            if (ObjectUtil.isNotNull(l.getPercentage()) && l.getPercentage().equals(100)) {
                vo.setStatus(4);
            }

            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }

    /**
     * 查询任务详情
     *
     * @param id
     * @return
     */
    @Override
    public TaskDetailsByIdVO getTaskDetailsById(Integer id) {
        TaskPubEntity pubEntity = getById(id);
        if (Objects.isNull(pubEntity)) {
            throw new CheckedException("当前任务不存在");
        }
        TaskDetailsByIdVO vo = new TaskDetailsByIdVO();

        BeanUtil.copyProperties(pubEntity, vo);
        List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(pubEntity.getJoinUser()), Integer.class);
        if (!joinUsers.isEmpty()) {
            List<SysUser> sysUsers = remoteUserService.userByIds(joinUsers);
            List<TaskDetailsByIdVO.JoinUser> users = new LinkedList<>();

            sysUsers.forEach(l -> {
                TaskDetailsByIdVO.JoinUser user = new TaskDetailsByIdVO.JoinUser();
                user.setJoinUser(l.getUserId());
                user.setJoinUserName(l.getName());
                user.setJoinJobNo(l.getUsername());
                users.add(user);
            });
            vo.setJoinUsers(users);

        }


        vo.setBeginTime(pubEntity.getBeginTime().format(DateTimeFormatter.ISO_DATE));
        vo.setEndTime(pubEntity.getEndTime().format(DateTimeFormatter.ISO_DATE));

        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(pubEntity.getDeptIds()), Integer.class);

        if (!deptIds.isEmpty()) {
            LinkedList<TaskDetailsByIdVO.DeptS> deptS = new LinkedList<>();
            List<SysDept> sysDepts = remoteDeptService.getDeptListById(deptIds);

            sysDepts.forEach(l -> {
                TaskDetailsByIdVO.DeptS dept = new TaskDetailsByIdVO.DeptS();
                dept.setDeptIds(l.getDeptId());
                dept.setDeptIdName(l.getName());
                deptS.add(dept);
            });

            vo.setDeptS(deptS);
        }


        return vo;
    }

    /**
     * 待审批任务撤销
     *
     * @param id
     * @return
     */
    @Override
    public Boolean revoke(Integer id) {
        TaskPubEntity pubEntity = getById(id);
        pubEntity.setStatus(0);
        this.baseMapper.updateById(pubEntity);
        return Boolean.TRUE;
    }

    /**
     * 修改任务
     *
     * @param dto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateTask(TaskPubUpdateDto dto) {

        final Integer createUser = SecurityUtils.getUser().getId();
        String username = SecurityUtils.getUser().getUsername();
        SysUser sysUser = remoteUserService.userByUserName(username);

        TaskPubEntity entity = getById(dto.getId());
        BeanUtil.copyProperties(dto, entity, "joinUser");
        entity.setCreateUser(createUser);
        entity.setCreateUserName(sysUser.getName());
        entity.setCorpId(CorpContextHolder.getCorpId());
        entity.setTenantId(TenantContextHolder.getTenantId());
        entity.setBeginTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getBeginTime() + " 00:00:00", "yyyy-MM-dd HH:mm:ss")));
        entity.setEndTime(DateUtil.toLocalDateTime(DateUtil.parse(dto.getEndTime() + " 23:59:59", "yyyy-MM-dd HH:mm:ss")));
        entity.setDeptIds(JSONUtil.toJsonStr(dto.getDeptIds()));

        List<SysUser> userList = new ArrayList<>();
        if (!dto.getDeptIds().isEmpty()) {
            userList = remoteUserService.userByDeptIds(dto.getDeptIds(), SecurityConstants.FROM_IN);
        }

        Set<Integer> userIds = new LinkedHashSet<>();
        Set<String> userJobNos = new LinkedHashSet<>();

        userList.forEach(u -> {
            userIds.add(u.getUserId());
            userJobNos.add(u.getUsername());
        });
        if (dto.getJoinUser() != null && !dto.getJoinUser().isEmpty()) {
            userIds.addAll(dto.getJoinUser());
        }
        if (dto.getJoinJobNo() != null && !dto.getJoinJobNo().isEmpty()) {
            userJobNos.addAll(dto.getJoinJobNo());
        }

        // 排除admin
        userIds.remove(1);
        userJobNos.remove("admin");

        entity.setJoinUser(JSONUtil.toJsonStr(userIds));
        entity.setJoinJobNo(JSONUtil.toJsonStr(userJobNos));

        return updateById(entity);
    }

    /**
     * 任务启动/结束 定时 一天一次
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
//    @Async
    public void startTask() {
        //启动任务发布
        List<TaskPubEntity> list = list(Wrappers.<TaskPubEntity>lambdaQuery()
                .eq(TaskPubEntity::getStatus, 1)
                .le(TaskPubEntity::getBeginTime, LocalDateTime.now()));
        if (!list.isEmpty()) {

            list.forEach(l -> {
                l.setStatus(2);
                List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(l.getJoinUser()), Integer.class);
                List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(l.getDeptIds()), Integer.class);
                List<WorkEmployeeEntity> employeeEntityList = new LinkedList<>();
                List<WorkEmployeeEntity> employeeEntities = new LinkedList<>();
                if (!deptIds.isEmpty()) {
                    List<SysDept> lowerDeptsByList = remoteDeptService.getLowerDeptsByList(deptIds);

                    employeeEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                            .in(WorkEmployeeEntity::getWxMainDepartmentId, lowerDeptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList())));
                }
                if (!joinUsers.isEmpty()) {
                    List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());
                    employeeEntities = workEmployeeService
                            .list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                                    .in(WorkEmployeeEntity::getWxUserId, collect));
                }

                employeeEntities.addAll(employeeEntityList);
                List<WorkEmployeeEntity> collect = Stream.of(employeeEntities, employeeEntityList)
                        .flatMap(Collection::stream).distinct().collect(Collectors.toList());

                //发送金融提醒给客户经理
                collect.forEach(ll -> {
                    Integer corpId = ll.getCorpId();
                    String wxCorpId = corpService.getById(corpId).getWxCorpId();
                    JSONObject object = new JSONObject();

                    object.put("content", StrUtil.format(BehaviorTrackFormatConst.TASKTOEOMPLOYEE, ll.getName(), ll.getWxUserId()));

                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("touser", ll.getWxUserId());
                    jsonObject.put("msgtype", "text");
                    jsonObject.put("agentid", corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
                    jsonObject.put("text", object);
                    String s = jsonObject.toString();
                    WxApiUtils.sendMsgToEmployeeByString(s, corpId, wxCorpId);
                });

            });
            updateBatchById(list);

        }

        //结束任务发布
        List<TaskPubEntity> entities = list(Wrappers.<TaskPubEntity>lambdaQuery()
                .eq(TaskPubEntity::getStatus, 2)
                .le(TaskPubEntity::getEndTime, LocalDateTime.now()));
        if (!entities.isEmpty()) {
            entities.forEach(l -> {
                l.setStatus(3);
            });
            updateBatchById(entities);
        }
    }

    /**
     * 统计员工完成任务情况
     */
    public void statisticsTask(Integer taskId) {

        TaskPubEntity taskPubEntity = getById(taskId);
        String beginTime = DateUtil.format(taskPubEntity.getBeginTime(), dateFormat);
        String endTime = DateUtil.format(taskPubEntity.getEndTime(), dateFormat);

        List<CpTaskPubEmpEntity> list = cpTaskPubEmpService.list(Wrappers.<CpTaskPubEmpEntity>lambdaQuery().eq(CpTaskPubEmpEntity::getTaskPubId, taskId));

        AtomicReference<Integer> count = new AtomicReference<>(0);
        AtomicReference<Integer> addCounts = new AtomicReference<>(0);

        AtomicReference<Integer> countss = new AtomicReference<>(new Integer(0));

        if (!list.isEmpty()) {
            list.forEach(l -> {

                SysUser sysUser = remoteUserService.userById(l.getEmployeeId());
                WorkEmployeeEntity workEmployeeEntity = workEmployeeService.getOne(Wrappers.<WorkEmployeeEntity>lambdaQuery().eq(WorkEmployeeEntity::getWxUserId, sysUser.getUsername()));

                if (ObjectUtil.isEmpty(workEmployeeEntity)) {
                    return;
                }

                Integer addCount = workContactEmployeeService.getEmployeeAddCount(workEmployeeEntity.getId(), beginTime, endTime);
                l.setCrmCount(addCount);
                int min = Math.min((addCount * 100 / l.getGoalCount()), 100);

                count.updateAndGet(v -> v + min);
                l.setPercentage(min);

                addCounts.updateAndGet(v -> v + addCount);

                Integer otherCount = workContactEmployeeService.getEmployeeOtherCount(workEmployeeEntity.getId(), beginTime, endTime);
                l.setOtherCount(otherCount);
                if (addCount >= l.getGoalCount()) {
                    l.setStatus(1);
                    countss.updateAndGet(v -> v + 1);
                }
            });
            cpTaskPubEmpService.updateBatchById(list);


            taskPubEntity.setPercentage(Math.min((countss.get() * 100 / list.size()), 100));
            taskPubEntity.setAddCount(addCounts.get());
            updateById(taskPubEntity);


        }

    }

    /**
     * 已完成任务成员列表
     *
     * @param taskId
     * @param page
     * @return
     */
    @Override
    public Page<TaskDetailsByEmployeeVO> getCompleteEmployee(Integer taskId, Page page) {
        //更新客户经理完成任务情况
        statisticsTask(taskId);
        page = (Page) cpTaskPubEmpService.page(page, Wrappers.<CpTaskPubEmpEntity>lambdaQuery()
                .eq(CpTaskPubEmpEntity::getTaskPubId, taskId).eq(CpTaskPubEmpEntity::getStatus, 1)
                .orderByDesc(CpTaskPubEmpEntity::getCreateTime));

        List<TaskDetailsByEmployeeVO> vos = new LinkedList<>();

        List<CpTaskPubEmpEntity> list = page.getRecords();
        list.forEach(l -> {
            TaskDetailsByEmployeeVO vo = new TaskDetailsByEmployeeVO();
            BeanUtil.copyProperties(l, vo);
            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }

    /**
     * 未完成任务成员列表
     *
     * @param taskId
     * @param page
     * @return
     */
    @Override
    public Page<TaskDetailsByEmployeeVO> getIncompleteEmployee(Integer taskId, Page page) {
        //更新客户经理完成任务情况
        statisticsTask(taskId);
        page = (Page) cpTaskPubEmpService.page(page, Wrappers.<CpTaskPubEmpEntity>lambdaQuery()
                .eq(CpTaskPubEmpEntity::getTaskPubId, taskId).eq(CpTaskPubEmpEntity::getStatus, 0)
                .orderByDesc(CpTaskPubEmpEntity::getCreateTime));

        List<TaskDetailsByEmployeeVO> vos = new LinkedList<>();

        List<CpTaskPubEmpEntity> list = page.getRecords();
        list.forEach(l -> {
            TaskDetailsByEmployeeVO vo = new TaskDetailsByEmployeeVO();
            BeanUtil.copyProperties(l, vo);
            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }


    /**
     * 一键提醒未完成任务成员
     *
     * @param taskId
     */
    @Override
    public void oneClickReminder(Integer taskId) {
        statisticsTask(taskId);
        List<CpTaskPubEmpEntity> list = cpTaskPubEmpService
                .list(Wrappers.<CpTaskPubEmpEntity>lambdaQuery()
                        .eq(CpTaskPubEmpEntity::getTaskPubId, taskId)
                        .eq(CpTaskPubEmpEntity::getStatus, 0));
        TaskPubEntity taskPubEntity = getById(taskId);

        List<Integer> employeeIds = list.stream().map(CpTaskPubEmpEntity::getEmployeeId).collect(Collectors.toList());
        if (!employeeIds.isEmpty()) {
            List<SysUser> sysUsers = remoteUserService.userByIds(employeeIds);

            //发送金融提醒通知客户经理
            sysUsers.forEach(l -> {
                //获取发送应用id
                Integer corpId = taskPubEntity.getCorpId();
                String wxCorpId = corpService.getById(corpId).getWxCorpId();
                JSONObject object = new JSONObject();
                object.put("content", StrUtil.format(BehaviorTrackFormatConst.TASKTOEOMPLOYEEBYREMIND, taskPubEntity.getTitle(), l.getUsername()));

                JSONObject jsonObject = new JSONObject();
                jsonObject.put("touser", l.getUsername());
                jsonObject.put("msgtype", "text");
                jsonObject.put("agentid", corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
                jsonObject.put("text", object);
                String s = jsonObject.toString();
                WxApiUtils.sendMsgToEmployeeByString(s, corpId, wxCorpId);
            });
        }


    }

    /**
     * 任务完成情况统计
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void taskCompletionStatistics() {
        List<TaskPubEntity> list = list(Wrappers.<TaskPubEntity>lambdaQuery().eq(TaskPubEntity::getStatus, 2));
        list.forEach(l -> {
            statisticsTask(l.getId());
        });
    }

    /**
     * 发布任务
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean releaseTaskById(Integer id) {
        List<Integer> statusList = new ArrayList<>();
        statusList.add(0);
        statusList.add(6);
        TaskPubEntity pubEntity = getOne(Wrappers.<TaskPubEntity>lambdaQuery().eq(TaskPubEntity::getId, id)
                .in(TaskPubEntity::getStatus, statusList)
                .ge(TaskPubEntity::getEndTime, LocalDateTime.now()));
        if (ObjectUtil.isEmpty(pubEntity)) {
            throw new CheckedException("当前任务可能不是可发布状态或者已超过任务结束时间");
        }
        pubEntity.setStatus(5);
        return updateById(pubEntity);
    }

    /**
     * 审核任务
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approvalTaskById(Integer id, String  opinion, Integer state) {
        TaskPubEntity pubEntity = getOne(Wrappers.<TaskPubEntity>lambdaQuery().eq(TaskPubEntity::getId, id)
                .eq(TaskPubEntity::getStatus, 5)
                .ge(TaskPubEntity::getEndTime, LocalDateTime.now()));
        if (ObjectUtil.isEmpty(pubEntity)) {
            throw new CheckedException("当前任务可能不是待审批状态或者已超过任务结束时间");
        }

        Integer createUserId = SecurityUtils.getUser().getId();
        String createUserName = SecurityUtils.getUser().getUsername();
        Long approvalId = sequence.nextValue();
        CpApprovalEntity approvalEntity = new CpApprovalEntity();
        approvalEntity.setId(approvalId);
        approvalEntity.setItemId(String.valueOf(pubEntity.getId()));
        approvalEntity.setItemType(8);
        approvalEntity.setApprovalType(state);
        approvalEntity.setApprovalUserId(createUserId);
        approvalEntity.setApprovalUserName(createUserName);
        approvalEntity.setApprovalPreState(pubEntity.getStatus());
        pubEntity.setOpinion(opinion);
        if (state == 1) {
            pubEntity.setStatus(6);
            updateById(pubEntity);
            approvalEntity.setApprovalPostState(6);
            cpApprovalService.save(approvalEntity);
            return true;
        } else {
            approvalEntity.setApprovalPostState(1);
            cpApprovalService.save(approvalEntity);
        }

        List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(pubEntity.getJoinUser()), Integer.class);
        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(pubEntity.getDeptIds()), Integer.class);
        List<WorkEmployeeEntity> employeeEntityList = new LinkedList<>();
        List<WorkEmployeeEntity> employeeEntities = new LinkedList<>();

        if (!deptIds.isEmpty()) {
            List<SysDept> lowerDeptsByList = remoteDeptService.getLowerDeptsByList(deptIds);
            employeeEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getWxMainDepartmentId, lowerDeptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList())));
        }
        if (!joinUsers.isEmpty()) {
            List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());
            employeeEntities = workEmployeeService
                    .list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                            .in(WorkEmployeeEntity::getWxUserId, collect));
        }

        employeeEntities.addAll(employeeEntityList);
        List<WorkEmployeeEntity> collect = Stream.of(employeeEntities, employeeEntityList)
                .flatMap(Collection::stream).distinct().collect(Collectors.toList());
        List<CpTaskPubEmpEntity> entities = new LinkedList<>();

        List<String> list = collect.stream().map(WorkEmployeeEntity::getWxUserId).collect(Collectors.toList());

        List<SysUser> userNames = remoteUserService.userByUserNames(list);

        //写入任务指定的客户经理信息
        userNames.forEach(ll -> {
            CpTaskPubEmpEntity entity = new CpTaskPubEmpEntity();
            entity.setDeptId(ll.getDeptId());
            entity.setCrmCount(0);
            entity.setOtherCount(0);
            entity.setEmployeeId(ll.getUserId());
            entity.setEmployeeName(ll.getName());
            entity.setGoalCount(pubEntity.getGoalCount());
            entity.setStatus(0);
            entity.setTaskPubId(pubEntity.getId());
            entity.setCorpId(CorpContextHolder.getCorpId());
            entity.setTenantId(TenantContextHolder.getTenantId());
            entity.setPercentage(0);
            SysDept listBy = remoteDeptService.getDeptListBy(ll.getDeptId());
            if (ObjectUtil.isNotNull(listBy)) {
                entity.setDeptName(listBy.getName());
            }

            entities.add(entity);
        });

        if (!entities.isEmpty()) {
            cpTaskPubEmpService.saveBatch(entities);
        }


        pubEntity.setStatus(1);
        if (pubEntity.getBeginTime().isBefore(LocalDateTime.now())) {
            sendMessage(pubEntity);
            pubEntity.setStatus(2);
        }
        return updateById(pubEntity);
    }

    private void sendMessage(TaskPubEntity entity) {

        List<Integer> joinUsers = JSONUtil.toList(JSONUtil.parseArray(entity.getJoinUser()), Integer.class);
        List<Integer> deptIds = JSONUtil.toList(JSONUtil.parseArray(entity.getDeptIds()), Integer.class);
        List<WorkEmployeeEntity> employeeEntityList = new LinkedList<>();
        List<WorkEmployeeEntity> employeeEntities = new LinkedList<>();
        if (!deptIds.isEmpty()) {
            List<SysDept> lowerDeptsByList = remoteDeptService.getLowerDeptsByList(deptIds);

            employeeEntityList = workEmployeeService.list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                    .in(WorkEmployeeEntity::getWxMainDepartmentId, lowerDeptsByList.stream().map(SysDept::getDeptId).collect(Collectors.toList())));
        }
        if (!joinUsers.isEmpty()) {
            List<String> collect = remoteUserService.userByIds(joinUsers).stream().map(SysUser::getUsername).collect(Collectors.toList());
            employeeEntities = workEmployeeService
                    .list(Wrappers.<WorkEmployeeEntity>lambdaQuery()
                            .in(WorkEmployeeEntity::getWxUserId, collect));
        }

        employeeEntities.addAll(employeeEntityList);
        List<WorkEmployeeEntity> collect = Stream.of(employeeEntities, employeeEntityList)
                .flatMap(Collection::stream).distinct().collect(Collectors.toList());

        //发送金融提醒
        collect.forEach(ll -> {
            Integer corpId = ll.getCorpId();
            String wxCorpId = corpService.getById(corpId).getWxCorpId();
            JSONObject object = new JSONObject();

            object.put("content", StrUtil.format(BehaviorTrackFormatConst.TASKTOEOMPLOYEE, ll.getName(), ll.getWxUserId()));

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("touser", ll.getWxUserId());
            jsonObject.put("msgtype", "text");
            jsonObject.put("agentid", corpService.getWxSendMsgAgentIdByWxCorpId(wxCorpId));
            jsonObject.put("text", object);
            String s = jsonObject.toString();
            WxApiUtils.sendMsgToEmployeeByString(s, corpId, wxCorpId);
        });
    }


    @Override
    public Page<ToDoListVO> getToDoList(Page page, String userId, Integer status, Integer type) {
        List<ToDoListVO> vos = new LinkedList<>();
        SysUser sysUser = remoteUserService.userByUserName(userId);

        if (ObjectUtil.isEmpty(sysUser)){
            throw new CheckedException("成员id出错");

        }
        page = cpTaskPubEmpService.getToDoList(page, sysUser.getUserId(), status, type);
        List<ToDoListBO> listVOS = page.getRecords();

        listVOS.forEach(l -> {
            ToDoListVO vo = new ToDoListVO();
            if (ObjectUtil.isNotNull(l.getCmtid())) {
                vo.setId(l.getCmtid());
                vo.setIsMoments(0);
                vo.setStatus(l.getStatus());

                vo.setBeginTime(DateUtil.formatDate(DateUtil.date(l.getBegintime())));
                vo.setEndTime(DateUtil.formatDate(DateUtil.date(l.getEndtime())));
                vo.setMediaId(JSONUtil.toList(JSONUtil.parseArray(l.getMediaId()), String.class));
                vo.setTitle(l.getCmttitle());
                vo.setCreateUserName(l.getCmtCreateUserName());
            } else {
                vo.setId(l.getCtpid());
                vo.setIsMoments(1);
                vo.setStatus(l.getStatus());

                vo.setBeginTime(DateUtil.formatDate(DateUtil.date(l.getBegintime())));
                vo.setEndTime(DateUtil.formatDate(DateUtil.date(l.getEndtime())));
                vo.setAddCount(l.getAddCount());
                vo.setTitle(l.getCtptitle());
                vo.setCreateUserName(l.getCtpCreateUserName());
                if (ObjectUtil.isEmpty(l.getPercentage())){
                    vo.setPercentage(0);
                }else {
                    vo.setPercentage(l.getPercentage());
                }
            }

            vo.setContent(l.getContent());

            if (StrUtil.isNotBlank(l.getImgUrl())) {
                List<String> list = JSONUtil.toList(JSONUtil.parseArray(l.getImgUrl()), String.class);
                vo.setImgUrl(list);
            }

            if (StrUtil.isNotBlank(l.getVideoUrl())) {
                List<String> list = JSONUtil.toList(JSONUtil.parseArray(l.getVideoUrl()), String.class);
                vo.setVideoUrl(list);
            }

            if (StrUtil.isNotBlank(l.getLinkUrl())) {
                cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(l.getLinkUrl());
                vo.setLinkUrl(jsonObject);
            }


            vos.add(vo);
        });

        page.setRecords(vos);
        return page;
    }

    /**
     * 删除到期期30天 任务
     */
    @Override
    @Async
    public void deleteOverdueTasks() {
        List<TaskPubEntity> overdueTasks = baseMapper.getOverdueTasks();
        if (!overdueTasks.isEmpty()) {
            removeByIds(overdueTasks.stream().map(TaskPubEntity::getId).collect(Collectors.toList()));
        }

    }

    @Override
    public List<TaskPubEntity> getTaskListForRedpack(String wxUserId, Integer taskType) {
        wxUserId = "\"" + wxUserId + "\"";
        return baseMapper.getTaskListForRedpack(wxUserId, taskType);
    }
}
